Přeskočit na hlavní obsah
  1. Posts/

Spring Security, SAML & ADFS: Implementace

·4 min

Posledně jsme se vyřádili na konfiguraci, tak teď už jen zbývá to nabouchat v tom Springu, ne? Dobrá zpráva je, že pokud budete následovat Reference Documentation, bude vám Spring SAML a ADFS fungovat out-of-the-box.

Špatná zpráva je, že pokud budete chtít použít Java configuration, nemáte se moc kde inspirovat. Pokud vím, tak k dnešnímu dni jsou k dispozici jen dva příklady:

Dalším benefitem mého příspěvku a ukázkového projektu je, že používají aktuální verzi Spring Frameworku a Spring Security, tedy verzi 5 (v tomhle asi budu chviličku unikátní). Třešničkou na dortu je pak buildování pomocí Gradle (protože kdo by ještě chtěl v dnešní době používat Maven, že jo? 😜

Závislosti #

Pro zdar operace budeme potřebovat následující závislosti:

Drobná Gradle poznámka: Protože používám současnou verzi Gradlu, používám konfiguraci implementation. Pro starší verze Gradle (2.14.1-) použijte původní (nyní deprecated) konfiguraci compile.

Spring SAML Configuration #

Ať už se použije XML, nebo Java konfigurace, bude to v každém případě velmi dlouhý soubor. Velmi. I když nebudu počítat téměř 40 řádek importů, i tak zabere ta nejzákladnější konfigurace zhruba 5 obrazovek. Víc se mi to ořezat nepodařilo.

Ale nebojte se, nebudu vás oblažovat každým detailem. Jen vypíchnu to zajímavé, vynechám co jsem zmiňoval v minulém díle o konfiguraci a pro zbytek konfigurace vás odkážu do svého repozitáře, kde si to můžete vychutnat celé: SecurityConfiguration.java.

Nastavení HttpSecurity #

Nebudu příliš zabíhat do podrobností, jak funguje samotné Spring Security (prostě chrání pomocí filtrů určité URL/zdroje) a podívám se na jedno konkrétní nastavení:

  • Vypnuté CSRF. U SAMLu nedává CSRF moc smysl — SAML requesty jsou podepsané privátním klíčem daného SP, jehož veřejný klíč je zaregistrován na použitém IdP.
  • Přídání dvou filtrů: jeden pro SAML metadata (metadataGeneratorFilter), druhý řeší samotný SAML mechanismus (samlFilter).
  • Definice URL, které vyžadují autentikaci (/user).
  • Podstrčení SAML entry pointu namísto přihlašovacího formuláře (loginPage("/saml/login")).
  • Přesměrování na root kontext aplikace po úspěšném odhlášení (logoutSuccessUrl("/")).

SAML filtry #

Základem jak Spring Security, tak Spring Security SAMLu jsou filtry — odchytí HTTP(S) komunikaci a transparentně aplikují zabezpečení aplikace. V případě SAMLu je těch filtrů celá smečka, ale v zásadě řeší jen tři věci: přihlášení (SSO), odhlášení (SLO) a metadata. Čtvrtým mušketýrem může být ještě IdP discovery, ale tu v našem případě nemáme.

Key manager #

Všechny SAML zprávy, jež si IdP a SP vyměňují jsou podepsané privátním klíčem dané strany. Doporučuji mít pro SAML podpisový klíč separátní key store (nemíchat ho třeba s key storem, který potřebuje aplikační server pro HTTPS).

V naší ukázkové aplikaci je SAML key store na classpath — v jakémkoli jiném, než lokálním vývojovém prostředí, key store samozřejmě externalizujeme (nepřibalujeme do WARu) a hesla kryptujeme.

Podepisování SHA-256 #

V minulém díle jsem zmiňoval, že Spring SAML defaultně používá při podepisování algoritmus SHA-1, kdežto ADFS očekává SHA-256. Jedna strana se musí přizpůsobit. Doporučuji upravit aplikaci — použít SHA-256 není nic těžkého.

Výběr podpisového algoritmu se provádí při inicializaci SAMLu pomocí třídy SAMLBootstrap, která bohužel není konfigurovatelná. Pomůžeme si tak, že od třídy podědíme a potřebný algoritmus podstrčíme:

V konfiguraci pak třídu instancujeme následujícím způsobem. Mimochodem, povšimněte si, že beana je instancovaná jako static. To proto, aby inicializace proběhal velmi záhy při vytváření kontextu.

That’s All Folks! #

Tím se náš 3-dílný mini seriál o Spring Security, SAMLu a ADFS uzavírá. Samozřejmě, že bych mohl napsat ještě mnoho odstavců a nasdílet spoustu dalších gistů. Ale už by to bylo jen nošení housek do krámu.

Lepší bude, pokud si teď stáhnete ukázkový projekt sw-samuraj/blog-spring-security, trochu se povrtáte ve zdrojácích a na závěr v něm vyměníte soubor FederationMetadata.xml a zkusíte ho rozchodit vůči vašemu ADFS. Při troše štěstí by to mělo fungovat na první dobrou 🙂

Jako bonus pro odvážné — pokud se opravdu pustíte do těch zdrojových kódů — můžete v historii projektu najít další Spring Security ukázky (je to celkem rozumně otagovaný):

  • Výměna CSRF tokenu mezi Springem a Wicketem (tag local-ldap).
  • Multiple HttpSecurity — v jedné aplikaci: autentikace uživatele přes formulář a mutual-autentication REST služeb přes certifikát (tag form-login).
  • Autentikace vůči lokálnímu (embedovanému) LDAPu (tag local-ldap).
  • Autentikace vůči Active Directory (tag remote-ad).

Související články #